1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.reflect;
18  
19  import static org.hamcrest.Matchers.hasItemInArray;
20  import static org.hamcrest.Matchers.hasItems;
21  import static org.junit.Assert.assertArrayEquals;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertNotSame;
26  import static org.junit.Assert.assertNull;
27  import static org.junit.Assert.assertSame;
28  import static org.junit.Assert.assertThat;
29  import static org.junit.Assert.assertTrue;
30  import static org.junit.Assert.fail;
31  
32  import java.lang.reflect.Method;
33  import java.lang.reflect.Type;
34  import java.util.Arrays;
35  import java.util.HashMap;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Map;
39  
40  import org.apache.commons.lang3.ArrayUtils;
41  import org.apache.commons.lang3.math.NumberUtils;
42  import org.apache.commons.lang3.mutable.Mutable;
43  import org.apache.commons.lang3.mutable.MutableObject;
44  import org.apache.commons.lang3.ClassUtils.Interfaces;
45  import org.apache.commons.lang3.reflect.testbed.Annotated;
46  import org.apache.commons.lang3.reflect.testbed.GenericConsumer;
47  import org.apache.commons.lang3.reflect.testbed.GenericParent;
48  import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
49  import org.junit.Before;
50  import org.junit.Test;
51  
52  /**
53   * Unit tests MethodUtils
54   * @version $Id$
55   */
56  public class MethodUtilsTest {
57    
58      private static interface PrivateInterface {}
59      
60      static class TestBeanWithInterfaces implements PrivateInterface {
61          public String foo() {
62              return "foo()";
63          }
64      }
65      
66      public static class TestBean {
67  
68          public static String bar() {
69              return "bar()";
70          }
71  
72          public static String bar(final int i) {
73              return "bar(int)";
74          }
75  
76          public static String bar(final Integer i) {
77              return "bar(Integer)";
78          }
79  
80          public static String bar(final double d) {
81              return "bar(double)";
82          }
83  
84          public static String bar(final String s) {
85              return "bar(String)";
86          }
87  
88          public static String bar(final Object o) {
89              return "bar(Object)";
90          }
91          
92          public static void oneParameterStatic(final String s) {
93              // empty
94          }
95  
96          @SuppressWarnings("unused")
97          private void privateStuff() {
98          }
99  
100 
101         public String foo() {
102             return "foo()";
103         }
104 
105         public String foo(final int i) {
106             return "foo(int)";
107         }
108 
109         public String foo(final Integer i) {
110             return "foo(Integer)";
111         }
112 
113         public String foo(final double d) {
114             return "foo(double)";
115         }
116 
117         public String foo(final String s) {
118             return "foo(String)";
119         }
120 
121         public String foo(final Object o) {
122             return "foo(Object)";
123         }
124         
125         public void oneParameter(final String s) {
126             // empty
127         }
128     }
129 
130     private static class TestMutable implements Mutable<Object> {
131         @Override
132         public Object getValue() {
133             return null;
134         }
135 
136         @Override
137         public void setValue(final Object value) {
138         }
139     }
140 
141     private TestBean testBean;
142     private final Map<Class<?>, Class<?>[]> classCache = new HashMap<Class<?>, Class<?>[]>();
143 
144     @Before
145     public void setUp() throws Exception {
146         testBean = new TestBean();
147         classCache.clear();
148     }
149 
150     @Test
151     public void testConstructor() throws Exception {
152         assertNotNull(MethodUtils.class.newInstance());
153     }
154 
155     @Test
156     public void testInvokeMethod() throws Exception {
157         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
158                 (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
159         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo"));
160         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
161                 (Object[]) null));
162         assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo", 
163                 (Object[]) null, (Class<?>[]) null));
164         assertEquals("foo(String)", MethodUtils.invokeMethod(testBean, "foo",
165                 ""));
166         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo",
167                 new Object()));
168         assertEquals("foo(Object)", MethodUtils.invokeMethod(testBean, "foo",
169                 Boolean.TRUE));
170         assertEquals("foo(Integer)", MethodUtils.invokeMethod(testBean, "foo",
171                 NumberUtils.INTEGER_ONE));
172         assertEquals("foo(int)", MethodUtils.invokeMethod(testBean, "foo",
173                 NumberUtils.BYTE_ONE));
174         assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
175                 NumberUtils.LONG_ONE));
176         assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
177                 NumberUtils.DOUBLE_ONE));
178     }
179 
180     @Test
181     public void testInvokeExactMethod() throws Exception {
182         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo",
183                 (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
184         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo"));
185         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo",
186                 (Object[]) null));
187         assertEquals("foo()", MethodUtils.invokeExactMethod(testBean, "foo", 
188                 (Object[]) null, (Class<?>[]) null));
189         assertEquals("foo(String)", MethodUtils.invokeExactMethod(testBean,
190                 "foo", ""));
191         assertEquals("foo(Object)", MethodUtils.invokeExactMethod(testBean,
192                 "foo", new Object()));
193         assertEquals("foo(Integer)", MethodUtils.invokeExactMethod(testBean,
194                 "foo", NumberUtils.INTEGER_ONE));
195         assertEquals("foo(double)", MethodUtils.invokeExactMethod(testBean,
196                 "foo", new Object[] { NumberUtils.DOUBLE_ONE },
197                 new Class[] { Double.TYPE }));
198 
199         try {
200             MethodUtils
201                     .invokeExactMethod(testBean, "foo", NumberUtils.BYTE_ONE);
202             fail("should throw NoSuchMethodException");
203         } catch (final NoSuchMethodException e) {
204         }
205         try {
206             MethodUtils
207                     .invokeExactMethod(testBean, "foo", NumberUtils.LONG_ONE);
208             fail("should throw NoSuchMethodException");
209         } catch (final NoSuchMethodException e) {
210         }
211         try {
212             MethodUtils.invokeExactMethod(testBean, "foo", Boolean.TRUE);
213             fail("should throw NoSuchMethodException");
214         } catch (final NoSuchMethodException e) {
215         }
216     }
217 
218     @Test
219     public void testInvokeStaticMethod() throws Exception {
220         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
221                 "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
222         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
223                 "bar", (Object[]) null));
224         assertEquals("bar()", MethodUtils.invokeStaticMethod(TestBean.class,
225                 "bar", (Object[]) null, (Class<?>[]) null));
226         assertEquals("bar(String)", MethodUtils.invokeStaticMethod(
227                 TestBean.class, "bar", ""));
228         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(
229                 TestBean.class, "bar", new Object()));
230         assertEquals("bar(Object)", MethodUtils.invokeStaticMethod(
231                 TestBean.class, "bar", Boolean.TRUE));
232         assertEquals("bar(Integer)", MethodUtils.invokeStaticMethod(
233                 TestBean.class, "bar", NumberUtils.INTEGER_ONE));
234         assertEquals("bar(int)", MethodUtils.invokeStaticMethod(TestBean.class,
235                 "bar", NumberUtils.BYTE_ONE));
236         assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
237                 TestBean.class, "bar", NumberUtils.LONG_ONE));
238         assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
239                 TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
240         
241         try {
242             MethodUtils.invokeStaticMethod(TestBean.class, "does_not_exist");
243             fail("should throw NoSuchMethodException");
244         } catch (final NoSuchMethodException e) {
245         }
246     }
247 
248     @Test
249     public void testInvokeExactStaticMethod() throws Exception {
250         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class,
251                 "bar", (Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
252         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class,
253                 "bar", (Object[]) null));
254         assertEquals("bar()", MethodUtils.invokeExactStaticMethod(TestBean.class,
255                 "bar", (Object[]) null, (Class<?>[]) null));
256         assertEquals("bar(String)", MethodUtils.invokeExactStaticMethod(
257                 TestBean.class, "bar", ""));
258         assertEquals("bar(Object)", MethodUtils.invokeExactStaticMethod(
259                 TestBean.class, "bar", new Object()));
260         assertEquals("bar(Integer)", MethodUtils.invokeExactStaticMethod(
261                 TestBean.class, "bar", NumberUtils.INTEGER_ONE));
262         assertEquals("bar(double)", MethodUtils.invokeExactStaticMethod(
263                 TestBean.class, "bar", new Object[] { NumberUtils.DOUBLE_ONE },
264                 new Class[] { Double.TYPE }));
265 
266         try {
267             MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
268                     NumberUtils.BYTE_ONE);
269             fail("should throw NoSuchMethodException");
270         } catch (final NoSuchMethodException e) {
271         }
272         try {
273             MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
274                     NumberUtils.LONG_ONE);
275             fail("should throw NoSuchMethodException");
276         } catch (final NoSuchMethodException e) {
277         }
278         try {
279             MethodUtils.invokeExactStaticMethod(TestBean.class, "bar",
280                     Boolean.TRUE);
281             fail("should throw NoSuchMethodException");
282         } catch (final NoSuchMethodException e) {
283         }
284     }
285 
286     @Test
287     public void testGetAccessibleInterfaceMethod() throws Exception {
288         final Class<?>[][] p = { ArrayUtils.EMPTY_CLASS_ARRAY, null };
289         for (final Class<?>[] element : p) {
290             final Method method = TestMutable.class.getMethod("getValue", element);
291             final Method accessibleMethod = MethodUtils.getAccessibleMethod(method);
292             assertNotSame(accessibleMethod, method);
293             assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
294         }
295     }
296     
297     @Test
298     public void testGetAccessibleMethodPrivateInterface() throws Exception {
299         final Method expected = TestBeanWithInterfaces.class.getMethod("foo");
300         assertNotNull(expected);
301         final Method actual = MethodUtils.getAccessibleMethod(TestBeanWithInterfaces.class, "foo");
302         assertNull(actual);
303     }
304 
305     @Test
306     public void testGetAccessibleInterfaceMethodFromDescription()
307             throws Exception {
308         final Class<?>[][] p = { ArrayUtils.EMPTY_CLASS_ARRAY, null };
309         for (final Class<?>[] element : p) {
310             final Method accessibleMethod = MethodUtils.getAccessibleMethod(
311                     TestMutable.class, "getValue", element);
312             assertSame(Mutable.class, accessibleMethod.getDeclaringClass());
313         }
314     }
315 
316     @Test
317     public void testGetAccessiblePublicMethod() throws Exception {
318         assertSame(MutableObject.class, MethodUtils.getAccessibleMethod(
319                 MutableObject.class.getMethod("getValue",
320                         ArrayUtils.EMPTY_CLASS_ARRAY)).getDeclaringClass());
321     }
322 
323     @Test
324     public void testGetAccessiblePublicMethodFromDescription() throws Exception {
325         assertSame(MutableObject.class, MethodUtils.getAccessibleMethod(
326                 MutableObject.class, "getValue", ArrayUtils.EMPTY_CLASS_ARRAY)
327                 .getDeclaringClass());
328     }
329     
330     @Test
331    public void testGetAccessibleMethodInaccessible() throws Exception {
332         final Method expected = TestBean.class.getDeclaredMethod("privateStuff");
333         final Method actual = MethodUtils.getAccessibleMethod(expected);
334         assertNull(actual);
335     }
336 
337     @Test
338    public void testGetMatchingAccessibleMethod() throws Exception {
339         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
340                 ArrayUtils.EMPTY_CLASS_ARRAY, ArrayUtils.EMPTY_CLASS_ARRAY);
341         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
342                 null, ArrayUtils.EMPTY_CLASS_ARRAY);
343         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
344                 singletonArray(String.class), singletonArray(String.class));
345         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
346                 singletonArray(Object.class), singletonArray(Object.class));
347         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
348                 singletonArray(Boolean.class), singletonArray(Object.class));
349         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
350                 singletonArray(Byte.class), singletonArray(Integer.TYPE));
351         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
352                 singletonArray(Byte.TYPE), singletonArray(Integer.TYPE));
353         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
354                 singletonArray(Short.class), singletonArray(Integer.TYPE));
355         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
356                 singletonArray(Short.TYPE), singletonArray(Integer.TYPE));
357         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
358                 singletonArray(Character.class), singletonArray(Integer.TYPE));
359         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
360                 singletonArray(Character.TYPE), singletonArray(Integer.TYPE));
361         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
362                 singletonArray(Integer.class), singletonArray(Integer.class));
363         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
364                 singletonArray(Integer.TYPE), singletonArray(Integer.TYPE));
365         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
366                 singletonArray(Long.class), singletonArray(Double.TYPE));
367         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
368                 singletonArray(Long.TYPE), singletonArray(Double.TYPE));
369         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
370                 singletonArray(Float.class), singletonArray(Double.TYPE));
371         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
372                 singletonArray(Float.TYPE), singletonArray(Double.TYPE));
373         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
374                 singletonArray(Double.class), singletonArray(Double.TYPE));
375         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
376                 singletonArray(Double.TYPE), singletonArray(Double.TYPE));
377         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
378                 singletonArray(Double.TYPE), singletonArray(Double.TYPE));
379         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
380                 singletonArray(ParentObject.class), singletonArray(ParentObject.class));
381         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
382                 singletonArray(ChildObject.class), singletonArray(ParentObject.class));
383         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo",
384                 singletonArray(ParentObject.class), singletonArray(GrandParentObject.class));
385         expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testTwo",
386                 singletonArray(ChildObject.class), singletonArray(ChildInterface.class));
387     }
388 
389     @Test
390     public void testNullArgument() {
391         expectMatchingAccessibleMethodParameterTypes(TestBean.class, "oneParameter",
392                 singletonArray(null), singletonArray(String.class));
393     }
394 
395     @Test
396     public void testGetOverrideHierarchyIncludingInterfaces() {
397         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
398         final Iterator<MethodDescriptor> expected =
399             Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
400                 new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]),
401                 new MethodDescriptor(GenericConsumer.class, "consume", GenericConsumer.class.getTypeParameters()[0]))
402                 .iterator();
403         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.INCLUDE)) {
404             assertTrue(expected.hasNext());
405             final MethodDescriptor md = expected.next();
406             assertEquals(md.declaringClass, m.getDeclaringClass());
407             assertEquals(md.name, m.getName());
408             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
409             for (int i = 0; i < md.parameterTypes.length; i++) {
410                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
411             }
412         }
413         assertFalse(expected.hasNext());
414     }
415 
416     @Test
417     public void testGetOverrideHierarchyExcludingInterfaces() {
418         final Method method = MethodUtils.getAccessibleMethod(StringParameterizedChild.class, "consume", String.class);
419         final Iterator<MethodDescriptor> expected =
420             Arrays.asList(new MethodDescriptor(StringParameterizedChild.class, "consume", String.class),
421                 new MethodDescriptor(GenericParent.class, "consume", GenericParent.class.getTypeParameters()[0]))
422                 .iterator();
423         for (final Method m : MethodUtils.getOverrideHierarchy(method, Interfaces.EXCLUDE)) {
424             assertTrue(expected.hasNext());
425             final MethodDescriptor md = expected.next();
426             assertEquals(md.declaringClass, m.getDeclaringClass());
427             assertEquals(md.name, m.getName());
428             assertEquals(md.parameterTypes.length, m.getParameterTypes().length);
429             for (int i = 0; i < md.parameterTypes.length; i++) {
430                 assertTrue(TypeUtils.equals(md.parameterTypes[i], m.getGenericParameterTypes()[i]));
431             }
432         }
433         assertFalse(expected.hasNext());
434     }
435 
436     @Test
437     @Annotated
438     public void testGetMethodsWithAnnotation() throws NoSuchMethodException {
439         assertArrayEquals(new Method[0], MethodUtils.getMethodsWithAnnotation(Object.class, Annotated.class));
440 
441         Method[] methodsWithAnnotation = MethodUtils.getMethodsWithAnnotation(MethodUtilsTest.class, Annotated.class);
442         assertEquals(2, methodsWithAnnotation.length);
443         assertThat(methodsWithAnnotation, hasItemInArray(MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation")));
444         assertThat(methodsWithAnnotation, hasItemInArray(MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")));
445     }
446 
447     @Test(expected = IllegalArgumentException.class)
448     public void testGetMethodsWithAnnotationIllegalArgumentException1() {
449         MethodUtils.getMethodsWithAnnotation(FieldUtilsTest.class, null);
450     }
451 
452     @Test(expected = IllegalArgumentException.class)
453     public void testGetMethodsWithAnnotationIllegalArgumentException2() {
454         MethodUtils.getMethodsWithAnnotation(null, Annotated.class);
455     }
456 
457     @Test(expected = IllegalArgumentException.class)
458     public void testGetMethodsWithAnnotationIllegalArgumentException3() {
459         MethodUtils.getMethodsWithAnnotation(null, null);
460     }
461 
462     @Test
463     @Annotated
464     public void testGetMethodsListWithAnnotation() throws NoSuchMethodException {
465         assertEquals(0, MethodUtils.getMethodsListWithAnnotation(Object.class, Annotated.class).size());
466 
467         final List<Method> methodWithAnnotation = MethodUtils.getMethodsListWithAnnotation(MethodUtilsTest.class, Annotated.class);
468         assertEquals(2, methodWithAnnotation.size());
469         assertThat(methodWithAnnotation, hasItems(
470                 MethodUtilsTest.class.getMethod("testGetMethodsWithAnnotation"),
471                 MethodUtilsTest.class.getMethod("testGetMethodsListWithAnnotation")
472         ));
473     }
474 
475     @Test(expected = IllegalArgumentException.class)
476     public void testGetMethodsListWithAnnotationIllegalArgumentException1() {
477         MethodUtils.getMethodsListWithAnnotation(FieldUtilsTest.class, null);
478     }
479 
480     @Test(expected = IllegalArgumentException.class)
481     public void testGetMethodsListWithAnnotationIllegalArgumentException2() {
482         MethodUtils.getMethodsListWithAnnotation(null, Annotated.class);
483     }
484 
485     @Test(expected = IllegalArgumentException.class)
486     public void testGetMethodsListWithAnnotationIllegalArgumentException3() {
487         MethodUtils.getMethodsListWithAnnotation(null, null);
488     }
489     
490     private void expectMatchingAccessibleMethodParameterTypes(final Class<?> cls,
491             final String methodName, final Class<?>[] requestTypes, final Class<?>[] actualTypes) {
492         final Method m = MethodUtils.getMatchingAccessibleMethod(cls, methodName,
493                 requestTypes);
494         assertTrue(toString(m.getParameterTypes()) + " not equals "
495                 + toString(actualTypes), Arrays.equals(actualTypes, m
496                 .getParameterTypes()));
497     }
498 
499     private String toString(final Class<?>[] c) {
500         return Arrays.asList(c).toString();
501     }
502 
503     private Class<?>[] singletonArray(final Class<?> c) {
504         Class<?>[] result = classCache.get(c);
505         if (result == null) {
506             result = new Class[] { c };
507             classCache.put(c, result);
508         }
509         return result;
510     }
511 
512     public static class InheritanceBean {
513         public void testOne(final Object obj) {}
514         public void testOne(final GrandParentObject obj) {}
515         public void testOne(final ParentObject obj) {}
516         public void testTwo(final Object obj) {}
517         public void testTwo(final GrandParentObject obj) {}
518         public void testTwo(final ChildInterface obj) {}
519     }
520     
521     interface ChildInterface {}    
522     public static class GrandParentObject {}
523     public static class ParentObject extends GrandParentObject {}
524     public static class ChildObject extends ParentObject implements ChildInterface {}
525 
526     private static class MethodDescriptor {
527         final Class<?> declaringClass;
528         final String name;
529         final Type[] parameterTypes;
530 
531         MethodDescriptor(final Class<?> declaringClass, final String name, final Type... parameterTypes) {
532             this.declaringClass = declaringClass;
533             this.name = name;
534             this.parameterTypes = parameterTypes;
535         }
536     }
537 }